#ifndef _QUEUE_HPP_
#define _QUEUE_HPP_

#include <deque>
#include "lock.hpp"
#include "condition.hpp"

namespace thread
{

template <typename _T>
class Queue
{
	public :
		Queue()
			: _lock(),
			_cond()
		{
		}
		~Queue() {}

		void put(const _T & val);
		void get(_T & val);

		size_t size() const { return _queue_size; }
		bool empty() const { return (0 == _queue_size); }
	private :
		Lock _lock;
		Condition _cond;
		
		size_t _queue_size;
		std::deque<_T> _queue;		
};

template <typename _T>
void Queue<_T>::put(const _T& val)
{
	_lock.lock();
	bool empty = (_queue_size == 0);
	_queue.push_back(val);
	++ _queue_size;
	_lock.unlock();

	if (empty)
	{
		_cond.signal();
	}
}

template <typename _T>
void Queue<_T>::get(_T & val)
{
	_lock.lock();

	while (_queue.empty())
	{
		_cond.wait(_lock);
	}

	val = _queue.front();
	_queue.pop_front();
	-- _queue_size;

	_lock.unlock();
}

}

#endif

